using System;
using System.IO;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;

using System.Drawing;
using System.Drawing.Printing;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Reflection;
using System.CodeDom;

using Camalon.Drawing;

namespace Camalon.Drawing.Design
{

	/// <summary>
	/// ShapeContainerRootDesignerBase is the user interface we present to users when they
	/// create a new shape container.  Individual shapes can be visually designed
	/// on this container.  We also add a toolbox item filter to the class definition
	/// that requires any toolbox items to have the filter name of
    /// "Camalon.Drawing.Shape". We also define this filter name
	/// in the Shape base class.  This disables all toolbox items that are not derived
	/// from Shape.
	/// </summary>
	[ToolboxItemFilter("Camalon.Drawing.Shape", ToolboxItemFilterType.Allow)]//Require
	public class ShapeContainerRootDesignerBase: ComponentDocumentDesigner, IRootDesigner, IToolboxUser, ISupportAdornment
	{

		private DrawingPad  _view						= null;

		protected enum DesignEnvironment
		{
			V1_1,
			V2_0
		}

		protected DesignEnvironment Environment
		{
			get
			{
				if( System.Environment.Version.Major < 2 )
					return DesignEnvironment.V1_1;
				else return DesignEnvironment.V2_0;
			}
		}



		#region IDisposable Members
		
		protected override void Dispose(bool disposing)
		{
			if( disposing)
			{

				if( _view != null)
				{
					_view.Dispose();
					_view = null;
				}

				if( _mcsHelper != null)	
				{
					_mcsHelper.Dispose();_mcsHelper = null;
				}


				IComponentChangeService cs = this.ComponentChangeService;
				if (cs != null)
				{
					cs.ComponentRemoved	-=new ComponentEventHandler(OnComponentRemoved);
					cs.ComponentAdded	-=new ComponentEventHandler(OnComponentAdded);
					cs.ComponentChanged	-=new ComponentChangedEventHandler(OnComponentChanged);
				}


				if (this.SelectionService != null)
					this.SelectionService.SelectionChanged -=new EventHandler(OnSelectionChanged);

				if (this.DesignerHost != null) 
					this.DesignerHost.LoadComplete -=new EventHandler(OnDesignerHostLoadComplete);
			}
			
			base.Dispose (disposing);
		}
		#endregion

		#region Design-Time Poperties

		protected internal IShapeContainerProvider ShapeContainerProvider
		{
			get
			{
				return (IShapeContainerProvider)Component;
			}
		}

		protected internal ShapeContainer ShapeContainer
		{
			get
			{   
				return this.ShapeContainerProvider.ShapeContainer;
			}

		}

		//		//LOcation is overridden for all  in all components used in this container
		//		//-------------------------------------------------------------------------
		//		Point _location = new Point(17,17);
		//		[Category("Design")]
		//		[DesignOnly(true)]
		//		[Browsable(false)]
		//		public Point Location 
		//		{
		//			get{ return _location;}
		//			set{ if( _location != value) _location = value;	}
		//		}
		//		//-------------------------------------------------------------------------

		private Size _gridSize = new Size(10, 10);
		[Category("Design")]
		[DefaultValue(typeof(Size),"10,10")]
		[DesignOnly(true)]
		public Size GridSize
		{
			get
			{
				return _gridSize;
			}
			set
			{
				_gridSize = value;
				if (_view != null) _view.DrawingPanel.GridSize = value;
			}
		}


		private bool _rightToLeft = false;
		[Category("Design")]
		[DefaultValue(false)]
		[DesignOnly(true)]
		public bool RightToLeft
		{
			get
			{
				return _rightToLeft;
			}
			set
			{
				_rightToLeft = value;    
				if (_view != null)
					_view.RightToLeft = value ? System.Windows.Forms.RightToLeft.Yes : System.Windows.Forms.RightToLeft.No ;
			}
		}

		private bool _drawGrid = true;
		[Category("Design")]
		[DefaultValue(true)]
		[DesignOnly(true)]
		public bool ShowGrid//DrawGrid
		{
			get
			{
				return _drawGrid;
			}
			set
			{
				_drawGrid = value;
				if (_view != null) _view.DrawingPanel.DrawGrid = value;
			}
		}

		private int _gridPageSize = 5;
		[Category("Design")]
		[DefaultValue(5)]
		[DesignOnly(true)]
		public int GridPageSize
		{
			get 
			{
				return _gridPageSize;
			}
			set
			{
				if (value < 2) value = 2;
				_gridPageSize = value;

				if (_view == null) return;
                
				_view.DrawingPanel.GridPageSize = value;
			}
		}

		private bool _snapToGrid = true;
		[Category("Design")]
		[DefaultValue(true)]
		[DesignOnly(true)]
		public bool SnapToGrid
		{
			get
			{
				return _snapToGrid;
			}
			set
			{
				_snapToGrid = value;

				if (_view != null) _view.DrawingPanel.SnapToGrid = value;
			}
		}

		private Color _gridColor = Color.Silver;
		[Category("Design")]
		[DefaultValue(typeof(Color), "Silver")]
		[DesignOnly(true)]
		public Color GridColor
		{
			get
			{
				return _gridColor;
			}
			set
			{
				_gridColor = value;

				if (_view != null) _view.DrawingPanel.GridColor  = value;
			}

		}

		private int _trayHeight = 100;
		[DefaultValue(100)]
		[DesignOnly(true)]
		[Browsable( false)]
		public int TrayHeight
		{
			get { return _trayHeight;}
			set	
			{ 
				if( value == _trayHeight) return;

				_trayHeight = value;

				if (_view == null) return;

				_view.ComponentTray.Height = value;

			}
		}
	
		private bool _trayVisible = true;
		[Category("Design")]
		[Browsable( true)]
		[DefaultValue(true)]
		[DesignOnly(true)]
		public bool TrayVisible
		{
			get	{ return _trayVisible;}
			set	
			{   
				if( value == _trayVisible) return;

				_trayVisible = value;

				if (_view == null) return;

				_view.ComponentTray.Visible = value;

			}
		}


		[DesignOnly( true )]
		[Browsable( false )]
		[EditorBrowsable( EditorBrowsableState.Never )]
		[DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden)]
		public int ShapeIndex // Hide on Root
		{
			get
			{ 
				return -1;
			}
		}


		[Browsable(false)]
		[Category("Shapes")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public ShapeCollection Shapes
		{
			get
			{
				return this.ShapeContainer.Shapes;
			}
		}


		#endregion Design-Time Poperties

		#region Overrides

		protected override void PreFilterProperties(IDictionary properties)
		{
			
			base.PreFilterProperties (properties);
	
	
			// and add the locked property
			//

			properties["GridColor"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"GridColor", 
				typeof(Color));


			properties["SnapToGrid"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"SnapToGrid", 
				typeof(bool));

			properties["GridPageSize"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"GridPageSize", 
				typeof(int));

			properties["TrayVisible"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"TrayVisible", 
				typeof(bool));

			properties["TrayHeight"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"TrayHeight", 
				typeof(int));

			properties["ShowGrid"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"ShowGrid", 
				typeof(bool));

			properties["GridSize"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"GridSize", 
				typeof(Size));

			properties["RightToLeft"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"RightToLeft", 
				typeof(bool));

			properties["ShapeIndex"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"ShapeIndex", 
				typeof(int));

			properties["Shapes"] = TypeDescriptor.CreateProperty(
				typeof(ShapeContainerRootDesignerBase), 
				"Shapes", 
				typeof(ShapeCollection));

		}


		
		public override void Initialize(IComponent component)
		{
			try
			{
				base.Initialize ( component );
				
		
				//We need to suspend the ComponentTray while designer is initializing
				//Otherwise in VS 2005 it does not restore the locations of components in tray
				this.ComponentTray.SuspendLayout();

				//------------------------------------------------------------------------------------------------
				// We need to listen to change events.  If a shape changes,
				// we need to invalidate our view.
				//------------------------------------------------------------------------------------------------
				IComponentChangeService cs = this.ComponentChangeService;
				if (cs != null)
				{
					cs.ComponentRemoved+=new ComponentEventHandler(OnComponentRemoved);
					cs.ComponentAdded+=new ComponentEventHandler(OnComponentAdded);
					cs.ComponentChanged+=new ComponentChangedEventHandler(OnComponentChanged);
				
				}

				// ----------------------------------------------------------------------------------
				// Select our base shape.  By default there is nothing selected but that looks
				// strange (the property grid is empty).
				// ----------------------------------------------------------------------------------
				ISelectionService ss = this.SelectionService;
				if (ss != null)
				{
					ss.SelectionChanged +=new EventHandler(OnSelectionChanged);
                    _adornment = this.CreateAdornment(ss);//  new ShapeAdornment(this.ShapeContainer, ss, true);
                }

					
				//------------------------------------------------------------------------------------------
				// We want the user to be able to place shapes on other designers, like windows forms.
				// The user could always use the customize toolbox dialog to browse to the library this
				// shape is stored in, but that's not a very RAD way of doing things.  It's much more
				// convenient to place a toolbox item on the toolbox for this shape.  We do this with
				// a toolbox item called a "Linked Tool".  Linked tools are linked to a particular designer
				// host and are automatically removed when the solution containing this project is closed.
				// To create a linked tool we create a toolbox item that contains the fully qualified 
				// class name of the shape we're designing.  Unfortunatley, that name isn't available yet.
				// To work around this, we must wait until the designer is fully loaded, and then add
				// the toolbox item.  We can do this easily through the IDesignerHost interface:
				//-------------------------------------------------------------------------------------------
				if (this.DesignerHost != null) this.DesignerHost.LoadComplete +=new EventHandler(OnDesignerHostLoadComplete);


			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("RootDesigner::Initialize:"+ exc.StackTrace);
				throw exc;

			}
		}


		private void OnDesignerHostLoadComplete(object sender, EventArgs e)
		{
			IDesignerHost host = this.DesignerHost;
			host.LoadComplete -= new EventHandler(OnDesignerHostLoadComplete);


            string category ="My Shapes";
			// Now get a hold of the toolbox service and add an icon for our user control.  The
			// toolbox service will automatically maintain this icon as long as our file lives.
			//
			IToolboxService tbx = (IToolboxService)GetService(typeof(IToolboxService));

			if (tbx != null) 
			{
//				string fullClassName = host.RootComponentClassName;
//				ToolboxItem item = new ToolboxItem();
//				item.TypeName = fullClassName;
//                
//				int idx = fullClassName.LastIndexOf('.');
//				if (idx != -1) 
//				{
//					item.DisplayName = fullClassName.Substring(idx + 1);
//				}
//				else 
//				{
//					item.DisplayName = fullClassName;
//				}
//
//				item.Bitmap = new Bitmap(typeof(ShapeComponentTray), "CustomShapeContainer.bmp");
//				item.Bitmap.MakeTransparent();
//
//				// Toolbox items are mutable until Lock is called on them.  This
//				// allows them to be very flexible without requiring a bunch of
//				// different constructors.  Once lock is called, they are "fixed"
//				// and cannot be changed.  After creating a toolbox item you should
//				// always call Lock before handing it to the toolbox service.  Otherwise
//				// other people could change it on you.
//				item.Lock();
//
//				// A "linked" toolbox item is one that is linked to our designer.  It
//				// follows our designer, rather than living forever on the toolbox.
//				// The tool is automatically removed when the project is closed, and
//				// re-added when the project is opened again.
//				tbx.AddLinkedToolboxItem(item, category, host);

				//TO remove tool box category
				ToolboxItemCollection tbic = tbx.GetToolboxItems( category );
				foreach( ToolboxItem tbi in tbic) tbx.RemoveToolboxItem( tbi,category); 	
			}



		}

		
		#endregion Overrides

		#region ISupportAdornment Members

		private ShapeAdornment _adornment = null;
		[Browsable(false), DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden)]
		public ShapeAdornment Adornment
		{
			get
			{
                if (_adornment == null) CreateAdornment(this.SelectionService);
				return _adornment;
			}
		}

		public virtual ShapeAdornment CreateAdornment(/*Shape shape,*/ISelectionService selectionService)
		{
			return new ShapeAdornment(this.ShapeContainer, selectionService, true);
		}


		public ShapeAdornment GetAdornment(Shape shape)
		{
			if( shape == this.ShapeContainer) return Adornment;
       
			IDesignerHost host = this.DesignerHost;
            IDesigner designer = host.GetDesigner(shape);
            ISupportAdornment ad = designer as ISupportAdornment;

			if( ad == null) return null;

            if (ad.Adornment == null)
                ad.CreateAdornment(this.SelectionService);

			return ad.Adornment;
		}

		public IControlPointDesigner GetControlPointDesigner( Shape shape )
		{
			if( shape == this.ShapeContainer) return null;
			
			IDesignerHost host = this.DesignerHost;
			return host.GetDesigner( shape ) as IControlPointDesigner;
		}

		#endregion

		#region Services


		IUIService _uiService	= null;
		internal IUIService UIService
		{
			get
			{
				if( _uiService == null)
					_uiService = (IUIService)GetService(typeof(IUIService));

				return _uiService;
			}
		}

		IExtenderProviderService _extenderProviderService;
		internal IExtenderProviderService ExtenderProviderService
		{
			get
			{
				if( _extenderProviderService == null)
					_extenderProviderService = (IExtenderProviderService)GetService(typeof(IExtenderProviderService));

				return _extenderProviderService;
			}
		}

		IInheritanceService _inheritanceService = null;
		internal IInheritanceService InheritanceService
		{
			get
			{
				if( _inheritanceService == null)
					_inheritanceService = (IInheritanceService)GetService(typeof(IInheritanceService));

				return _inheritanceService;
			}
		}




		INameCreationService _nameCreationService = null;
		internal INameCreationService NameCreationService
		{
			get
			{
				if( _nameCreationService == null)
					_nameCreationService = (INameCreationService)GetService(typeof(INameCreationService));

				return _nameCreationService;
			
			}
		}


		IComponentChangeService _componentChangeService = null;
		internal IComponentChangeService ComponentChangeService
		{
			get
			{
				if( _componentChangeService == null)
					_componentChangeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));

				return _componentChangeService;
			}
		}


		ISelectionService _selectionService = null;
		internal ISelectionService SelectionService
		{
			get
			{
				if( _selectionService == null)
					_selectionService = (ISelectionService)GetService(typeof(ISelectionService));

				return _selectionService;
			}
		}

		IDesignerHost _designerHost = null;
		internal IDesignerHost DesignerHost
		{
			get
			{
				if( _designerHost == null) 
				{
					_designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
				}

				return _designerHost;
			}
		}


		IToolboxService _toolBoxService = null;
		internal IToolboxService ToolBoxService
		{
			get
			{
				if( _toolBoxService == null) 
					_toolBoxService = (IToolboxService)GetService(typeof(IToolboxService));

				return _toolBoxService;
			}
		}


		IMenuCommandService _menuCommandService = null;
		internal IMenuCommandService MenuCommandService
		{
			get
			{
				if( _menuCommandService == null) 
					_menuCommandService = (IMenuCommandService)GetService(typeof(IMenuCommandService));

				return _menuCommandService;
			}
		}

 
		private bool _selectionChanging = false;
		internal void SetSelectedComponents( ICollection components, SelectionTypes selectionType)
		{
			if( _selectionChanging) return;

			_selectionChanging = true;
			try
			{

//				FileWatcher.WriteLine("----Selected components----");
//				foreach( Component c in this.SelectionService.GetSelectedComponents())
//					FileWatcher.WriteLine(TypeDescriptor.GetComponentName( c ));

				ISelectionService ss = this.SelectionService;
				if (ss != null)
					ss.SetSelectedComponents(components, selectionType);



			}
			finally
			{
				_selectionChanging = false;
			}
							
		}

		#endregion Services

		#region IRootDesigner Implementations

		
		MenuCommandsHelper _mcsHelper;
		MenuCommandsHelper InitializeMenuCommands()
		{
			if( _mcsHelper != null) return _mcsHelper;

			IMenuCommandService mcs = this.MenuCommandService ;

			if( mcs == null) return null;
			try
			{

			_mcsHelper = new MenuCommandsHelper( mcs, false,  
					MenuCommands.SendToBack,
					MenuCommands.BringToFront,

					MenuCommands.KeyMoveLeft,
					MenuCommands.KeyMoveRight,
					MenuCommands.KeyMoveDown,
					MenuCommands.KeyMoveUp,

					MenuCommands.KeyNudgeDown,
					MenuCommands.KeyNudgeLeft,
					MenuCommands.KeyNudgeRight,
					MenuCommands.KeyNudgeUp,

					MenuCommands.KeyNudgeHeightDecrease	,
					MenuCommands.KeyNudgeHeightIncrease	,
					MenuCommands.KeyNudgeWidthDecrease	,
					MenuCommands.KeyNudgeWidthIncrease	,

					MenuCommands.KeySizeWidthDecrease	,
					MenuCommands.KeySizeWidthIncrease	,
					MenuCommands.KeySizeHeightIncrease	,
					MenuCommands.KeySizeHeightDecrease	,
				
					MenuCommands.KeyCancel,

					//MenuCommands.LockControls,// ShapeGroup has been excluded from project
					
					//To be implemented
					//------------------------------------------------------------
					MenuCommands.AlignLeft,
					MenuCommands.AlignBottom,
					MenuCommands.AlignHorizontalCenters,
					MenuCommands.AlignRight,
					MenuCommands.AlignToGrid,
					MenuCommands.AlignTop,
					MenuCommands.AlignVerticalCenters,
					
					MenuCommands.CenterHorizontally,
					MenuCommands.CenterVertically,
					
					MenuCommands.HorizSpaceConcatenate,
					MenuCommands.HorizSpaceDecrease,
					MenuCommands.HorizSpaceIncrease,
					MenuCommands.HorizSpaceMakeEqual,

					MenuCommands.SizeToControlHeight,
					MenuCommands.SizeToControl,
					MenuCommands.SizeToControlWidth,
					MenuCommands.SizeToGrid,

					MenuCommands.VertSpaceConcatenate,
					MenuCommands.VertSpaceDecrease,
					MenuCommands.VertSpaceIncrease,
					MenuCommands.VertSpaceMakeEqual,
					//-----------------------------------------------------------

					MenuCommands.SnapToGrid,
					MenuCommands.ShowGrid,
					MenuCommands.ViewGrid
					);

				#region Commented Shape Group Code
				//_mcsHelper.LockControls+=new EventHandler(OnToggleGroup);
				#endregion
				_mcsHelper[MenuCommands.SnapToGrid].Change+=new EventHandler(OnMenuSnapToGrid);
				_mcsHelper[MenuCommands.ShowGrid].Change+=new EventHandler(OnMenuShowGrid);
				_mcsHelper[MenuCommands.ViewGrid].Change+=new EventHandler(OnMenuShowGrid);

				_mcsHelper.Add();

				
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("InitializeMenuCommands:"+ exc.Message +"\n" + exc.StackTrace);
//				throw exc;
			}
			return _mcsHelper;

		}



		void View_Load(object sender, EventArgs e)
		{

            // MOVED TO GET VIEW: 02.03.2008
            //_view.DrawingPanel.GridSize = _gridSize;
            //_view.RightToLeft = _rightToLeft ? System.Windows.Forms.RightToLeft.Yes : System.Windows.Forms.RightToLeft.No;

            //_view.DrawingPanel.DrawGrid = _drawGrid;
            //_view.DrawingPanel.GridPageSize = _gridPageSize;
            //_view.DrawingPanel.SnapToGrid = _snapToGrid;
            //_view.DrawingPanel.GridColor = _gridColor;

            //_view.ComponentTray.Visible = _trayVisible;
            //_view.ComponentTray.Height = _trayHeight;

            //RefreshShapeIndexes();
            //_view.DrawingPanel.RecalculateScrollSize();
            //RefreshShapeStatus();


            //_view.ComponentTray.AddTrayControl(this.ComponentTray);
            //this.ComponentTray.ResumeLayout();
		}
		

		public DrawingPad DrawingPad
		{
			get{ return _view;}
		}


		private ComponentTray ComponentTray
		{
			get{ return this.Control as ComponentTray;}
		}

		
		object IRootDesigner.GetView(System.ComponentModel.Design.ViewTechnology technology)
			//public object GetView(System.ComponentModel.Design.ViewTechnology technology)
		{ //object IRootDesigner.GetView(System.ComponentModel.Design.ViewTechnology technology)
			try
			{


				if( _view == null) 
				{
                    //FileWatcher.WriteLine("GetView called");
                    _view = new DrawingPad( this,InitializeMenuCommands());

                    _view.ComponentTray.SizeChanged += new EventHandler(ComponentTray_SizeChanged);
                    _view.ComponentTray.VisibleChanged += new EventHandler(ComponentTray_VisibleChanged);
                    //_view.Load += new EventHandler(View_Load);

                    _view.DrawingPanel.GridSize = _gridSize;
                    _view.RightToLeft = _rightToLeft ? System.Windows.Forms.RightToLeft.Yes : System.Windows.Forms.RightToLeft.No;

                    _view.DrawingPanel.DrawGrid = _drawGrid;
                    _view.DrawingPanel.GridPageSize = _gridPageSize;
                    _view.DrawingPanel.SnapToGrid = _snapToGrid;
                    _view.DrawingPanel.GridColor = _gridColor;

                    _view.ComponentTray.Visible = _trayVisible;
                    _view.ComponentTray.Height = _trayHeight;

                    //EXCLUDED(TO TEST) 02.03.2008
                    //RefreshShapeIndexes();
                    //_view.DrawingPanel.RecalculateScrollSize();
                    //RefreshShapeStatus();

                    _view.ComponentTray.AddTrayControl(this.ComponentTray);
                    this.ComponentTray.ResumeLayout();//IMPORTANT to call


				}

				return _view;

			}
			catch ( Exception e)
			{
				FileWatcher.WriteLine("GetView:"+ e.StackTrace);
				throw e;
			}
		}

		System.ComponentModel.Design.ViewTechnology[] IRootDesigner.SupportedTechnologies
			//public System.ComponentModel.Design.ViewTechnology[] SupportedTechnologies
		{ //System.ComponentModel.Design.ViewTechnology[] IRootDesigner.SupportedTechnologies
			get
			{
				// Add ShapeContainerRootDesignerBase.SupportedTechnologies getter implementation
				return new ViewTechnology[] {ViewTechnology.Default};
			}
		}


		#endregion IRootDesigner Implementations

		#region IToolBoxUser Implementation

		//		private bool _toolPicked = false;
		
		protected internal void AddToolItem( ToolboxItem item , Point position, Point realPos)
		{
			// User has clicked and we need to create a new item.
			//
			IDesignerHost host = this.DesignerHost;
		
			// For each new item created, move it to the location
			// of the click.
			//
			if (host == null) throw new Exception("AddToolItem: DesignerHost is null!!!!");
			// By creating a transaction here, we create a single undo unit that
			// encompasses everything we do until we commit.  This way if the user
			// clicks the undo button, the entire add / size work is undone in a
			// single action.
			//
			try
			{
				using (DesignerTransaction trans = host.CreateTransaction("Creating " + item.DisplayName))
				{
					// Nearly all toolbox items create a single component.  However,
					// some toolbox items (like data components), may invoke some sort
					// of wizard within the CreateComponents method and can return
					// multiple components.  It's best just to be generic here and
					// always handle multiple components.
					IComponent[] newComponents = item.CreateComponents(host);

				
					//ShapeContainer sc = host.RootComponent as ShapeContainer;
					ShapeContainer sc = this.ShapeContainer;

					PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(Shape));

					Shape hitShape = null;
					foreach(Shape s in sc.Shapes)
					{
						if( s.Site == null) continue;
						if( s.HitTest( realPos )) hitShape = s;
					}
					if( this.ShapeContainer != null)
					{
						foreach(IComponent comp in newComponents)
						{
							ComponentDesigner d = host.GetDesigner( comp ) as ComponentDesigner;
							if( d != null) d.InitializeNewComponent(null);
					

							if (comp is Shape)
							{
								Shape shape = (Shape)comp;
								PropertyDescriptor prop = props["Position"];
								prop.SetValue(shape,position);
								if( shape is ShapeContainer) props["Status"].SetValue( shape, 2);
								if( shape.Pen == null ) props["Pen"].SetValue( shape,host.CreateComponent( typeof( ShapePen ) ));
							}

							if( hitShape == null) continue;

							
							if( comp is Outline)	props["Outline"].SetValue( hitShape,comp);
							if( comp is ShapeFill )	props["Fill"].SetValue( hitShape,comp);
							if( comp is ShapePen )	props["Pen"].SetValue( hitShape,comp);
						}

					}





					// Always commit a transaction when done.
					trans.Commit();
					// This notifies the toolbox service that we did create this control.  The
					// toolbox service generally sets the currently selected tool to null in
					// this call.
					IToolboxService ts = this.ToolBoxService;
					if (ts != null) ts.SelectedToolboxItemUsed();

					// Finally, now that the user has created a new item, we should
					// selected them in the selection service.
					SetSelectedComponents(newComponents, SelectionTypes.Replace);
						
				}
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("AddToolItem:"+ exc.StackTrace);
				throw exc;
			}
		}

		

		bool IToolboxUser.GetToolSupported(ToolboxItem item)
		{
			return true;
		}

		void IToolboxUser.ToolPicked(ToolboxItem item)
			//protected void ToolPicked( ToolboxItem item )
		{//void IToolboxUser.ToolPicked(ToolboxItem item)
			try
			{
				Point pt = _view.DrawingPanel.TransformPoint( new Point( 20,20 ));
				AddToolItem( item , pt, pt);
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("ToolPicked:"+ exc.Message);
			}

		}


		#endregion IToolBoxUser Implementation

		#region Private Methods
		bool _shapeIndexRefreshing = false;
		private void RefreshShapeIndexes()
		{	
			RefreshShapeIndexes( this.ShapeContainer );
		}

		private void RefreshShapeIndexes( ShapeContainer container )
		{

            //Call this when designer host load completed and when 
            //a component has been deleted
            _shapeIndexRefreshing = true;
            try
            {
                for (int i = 0; i < container.Shapes.Count; i++)
                    container.Shapes[i].ShapeIndex = i;
            }
            catch (Exception exc)
            {
                FileWatcher.WriteLine("RefreshShapeIndexes:" + exc.StackTrace);
                FileWatcher.WriteLine("RefreshShapeIndexes:" + exc.Message);
                throw exc;
            }
            finally
            {
                _shapeIndexRefreshing = false;
            }
		}

		private void RefreshShapeStatus( Shape shape )
		{
//			try
//			{
//				this.ShapeContainer.Status = 0;
//
//				IDesignerHost host = this.DesignerHost;
//
//				int status = 0;
//
//				if (shape is ShapeContainer) status |=2; //Set ChildContainer
//
//				PropertyDescriptor propMod = TypeDescriptor.GetProperties(shape)["Modifiers"];
//				if( propMod != null)
//				{
//					MemberAttributes ma = (MemberAttributes)propMod.GetValue( shape );
//					if( ma != MemberAttributes.Private && ma != MemberAttributes.Assembly  ) status |= 1;
//				}
//
//				if( status != shape.Status )
//					using (DesignerTransaction tx = host.CreateTransaction("Do not undo this operation"))
//					{
//						PropertyDescriptor prop = TypeDescriptor.GetProperties(shape)["Status"];
//						prop.SetValue(shape,status);// Set status
//						tx.Commit();
//					}
//				
//			}
//			catch( Exception exc)
//			{
//				FileWatcher.WriteLine("RefreshShapeStatus:"+ exc.StackTrace);
//				FileWatcher.WriteLine("RefreshShapeStatus:"+ exc.Message);
//				throw exc;
//			}
		}

		private void RefreshShapeStatus()
		{
			foreach( Shape shape in this.ShapeContainer.Shapes) RefreshShapeStatus( shape );
		}


		#endregion  Private Methods

		#region Event Handlers

		#region Commented ShapeGroup Code
//		private void OnToggleGroup(object sender, EventArgs e)
//		{
//			MenuCommand mcGroup = (MenuCommand)sender;
//
//			IDesignerHost host = this.DesignerHost;
//			ISelectionService ss = this.SelectionService;
//
//			if( mcGroup.Checked)
//			{
//				
//				using (DesignerTransaction trans = host.CreateTransaction("Ungroup shapes"))
//				{
//					ShapeGroup shapeGroup = ss.PrimarySelection as ShapeGroup;
//					
//					if( shapeGroup == null) { trans.Cancel(); return;}
//
//					SetSelectedComponents( shapeGroup.Shapes, SelectionTypes.Click);
//					
//					
//
//					foreach(Shape shape in shapeGroup.Shapes)
//						this.ShapeContainer.Shapes.Add( shape);
//
//
//					host.DestroyComponent( shapeGroup );
//
//					this.RefreshShapeIndexes();
//
//
//					trans.Commit();
//
//				}
//			}
//			else
//			{
//				using (DesignerTransaction trans = host.CreateTransaction("Group shapes"))
//				{
//					IList selectedShapes = (IList)ss.GetSelectedComponents();
//
//					ArrayList shapes = new ArrayList();
//					foreach( object shapeObject in selectedShapes ) 
//						if( shapeObject is Shape) shapes.Add( shapeObject);
//
//					//Sort array
//					//----------------------------------------------------------
//					for( int i = 0; i< shapes.Count; i++)
//					{
//						Shape shape_i = shapes[i] as Shape;
//						int minj = i;
//
//						for( int j = i+1; j< shapes.Count; j++)
//						{
//							Shape shape_j = shapes[j] as Shape;
//							if( shape_j.ShapeIndex < shape_i.ShapeIndex )
//								minj = j;
//						}
//
//						if( i == minj) continue;
//
//						object temp	= shapes[i];
//						shapes[i]	= shapes[minj];
//						shapes[minj] = temp;
//					}
//					//-----------------------------------------------------------
//
//
//
//					RectangleF bounds = ((Shape)shapes[0]).GetPathBounds();
//					foreach( Shape shape in shapes)
//						bounds = RectangleF.Union( bounds, shape.GetPathBounds());
//
//
//					ShapeGroup group = host.CreateComponent( typeof( ShapeGroup ) ) as ShapeGroup;
//					group.Bounds = bounds;
//					
//					this.ShapeContainer.Shapes.Add( group );
//
//					if( shapes.Count > 0)
//						foreach( Shape shape in shapes)
//						{
//							this.ShapeContainer.Shapes.Remove( shape );
//							group.Shapes.Add( shape);
//						}
//
//					this.RefreshShapeStatus();
//					this.RefreshShapeIndexes();
//					this.RefreshShapeIndexes( group );
//					
//					trans.Commit();
//
//					group.ResumeLayout();
//				}
//
//
//			}
//
//			this.ShapeContainer.ResumeLayout();
//			_view.DrawingPanel.Invalidate();
//
//		}
//
//
//		private void UpdateGroupCommandStatus()
//		{
//			if( this.DesignerHost.Loading) return;
//			//Grouping/Ungrouping
//			//-------------------------------------------------------------
//			//FileWatcher.WriteLine("UpdateGroupCommandStatus called");
//			if( _mcsHelper == null ) return;
//			ISelectionService ss = this.SelectionService;
//			MenuCommand mcGroup = _mcsHelper[StandardCommands.LockControls];
//			Shape primaryShape = ss.PrimarySelection as Shape;
//
//			if( primaryShape == null ||
//				!this.ShapeContainer.Shapes.Contains( primaryShape ) ||
//				primaryShape == this.ShapeContainer ||
//				( !(primaryShape is ShapeGroup) && (ss.SelectionCount <= 1)  ) ) 
//			{
//				mcGroup.Visible = mcGroup.Enabled  = false;
//			}
//			else
//			{
//				mcGroup.Visible = mcGroup.Enabled  = true;				
//				mcGroup.Checked = ss.SelectionCount == 1 && primaryShape is ShapeGroup;
//
//			}
//
//
//		}
//

		#endregion Commented ShapeGroup Code

		private void OnSelectionChanged(object sender, EventArgs e)
		{
			try
			{

				if( this.SelectionService.SelectionCount == 0)
					SetSelectedComponents( new IComponent[]{ this.ShapeContainer }, SelectionTypes.Primary);// SelectionTypes.Click);

				// Now invalidate the currently selected components.
				// ---------------------------------------------------------------------
				if( _view != null) _view.DrawingPanel.InvalidateSelectedBounds();

//				if( this.ComponentTray.AutoArrange ) this.ComponentTray.AutoArrange = false;

				#region Commented Shape Group Code
				//UpdateGroupCommandStatus();
				#endregion

			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine( "OnSelectionChanged :" + exc.StackTrace);
				FileWatcher.WriteLine( "OnSelectionChanged :" + exc.Message);
				throw exc;
			}
		}


		private void OnComponentChanged(object sender, ComponentChangedEventArgs e)
		{
			try
			{
				if(e.Member == null ) return;
				

				//---Shape properties-------------------------------------------------------------------------------
				if( !(e.Component is Shape)) return;



				if(e.Member.Name == "ShapeIndex")
				{

					
					//TODO:The shape might belong to a group...Chek this...
					if(_shapeIndexRefreshing || this.DesignerHost.Loading ) return;


					#region Commented Shape Group Code

//					if( e.Component is ShapeGroup)
//					{
//						//While undoing deleted Shape group, the shapes in the group also are
//						//added into the Shapes collection of the root. To prevent this:
//						ShapeGroup group = e.Component as ShapeGroup;
//
//						if( group.Shapes.Count > 0)
//						{
//							foreach( Shape s in group.Shapes)
//								if( this.ShapeContainer.Shapes.Contains( s))
//									this.ShapeContainer.Shapes.Remove( s);
//
//							RefreshShapeIndexes( group );
//
//							return;//Do not take any actions more
//						}
//					}

					#endregion

					Shape shape = (Shape)e.Component;
					int oldIndex = (int)e.OldValue;
					int newIndex = (int)e.NewValue;

                    //FileWatcher.WriteLine("Shapes Count=" + this.ShapeContainer.Shapes.Count);
                    //FileWatcher.WriteLine("OldIndex=" + oldIndex + "   NewIndex=" + newIndex);

                    if (oldIndex == -1 || newIndex == oldIndex)
                    {
                        //RefreshShapeIndexes();
                        return;
                    }

                    if (oldIndex >= this.ShapeContainer.Shapes.Count)
                    {
                        //RefreshShapeIndexes();
                        return;
                    }

					this.ShapeContainer.Shapes.RemoveAt(oldIndex);

					if( newIndex != -1 && newIndex < this.ShapeContainer.Shapes.Count)
						this.ShapeContainer.Shapes.Insert( newIndex, shape);
					else
					{
						this.ShapeContainer.Shapes.Add( shape );
						newIndex = this.ShapeContainer.Shapes.Count-1;
					}

					_view.DrawingPanel.InvalidateShapeBounds( 
						Rectangle.Union( Rectangle.Ceiling(this.ShapeContainer.Shapes[oldIndex].Bounds),
						Rectangle.Ceiling(this.ShapeContainer.Shapes[newIndex].Bounds )));

					RefreshShapeIndexes();

				}

			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnComponentChanged:"+ exc.StackTrace);
				FileWatcher.WriteLine("OnComponentChanged:"+ exc.Message);
				throw exc;
			}
		}


		private void OnComponentAdded(object sender, ComponentEventArgs e)
		{
			try
			{
				//if( _toolPicked ) return; //picking tool item


				Shape shape = e.Component as Shape;
				if( shape == null) return;// Not a shape


				IDesignerHost host = ( IDesignerHost)sender;
				if( host.Loading ) return;  // Project rebuild, do not add again

				

				//----------- Paste/Undo Operation ---------------------------------------------
				//FileWatcher.WriteLine( "OnComponentAdded called:" + TypeDescriptor.GetComponentName( e.Component));

				this.ShapeContainer.Shapes.Add( shape );

				RefreshShapeIndexes();

				SetSelectedComponents( new Shape[]{ shape }, SelectionTypes.Primary);// SelectionTypes.Click);
				//-------------------------------------------------------------------------

			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnComponentAdded:"+ exc.StackTrace);
				FileWatcher.WriteLine("OnComponentAdded:"+ exc.Message);
			}

		}



		private void OnComponentRemoved(object sender, ComponentEventArgs e)
		{
			try
			{

				if( this.DesignerHost.Loading) return;

				if( !(e.Component is Shape)) return;

				RectangleF bounds = Rectangle.Empty;
				Shape shape = (Shape)e.Component;
				bounds = shape.Bounds;


					//REMOVE UNUSED PENS
					//TODO: This crashes if inherited pens removed......
					//-------------------------------------------------------------------------
					ShapePen	pen		= shape.Pen;
					ShapeFill	fill	= shape.Fill;
			
					bool penFound	= false;
					bool fillFound	= false;
				
					if( this.ShapeContainer.Container.Components != null )
						foreach( Component c in  this.ShapeContainer.Container.Components)
						{
							Shape s = c as Shape;
							if(s== null || s == shape) continue;
							if( fill != null && s.Fill == fill) fillFound = true;
							if( pen  != null && s.Pen	== pen)  penFound = true;
						}


					if( !penFound  && pen  != null ) DesignerHost.DestroyComponent( pen );
					if( !fillFound && fill != null ) DesignerHost.DestroyComponent( fill );

					//-------------------------------------------------------------------------



				#region Commented Shape Group Code
				
					//Check whether shape is a Shape Group. If yes, add the grouped shapes
					//back to the root container, if not already added...
					//--------------------------------------------------------------------
//					if( shape is ShapeGroup )
//					{
//						ShapeGroup group = ( ShapeGroup)shape;
//						group.ResetTransform(  );
//						foreach( Shape s in group.Shapes )
//							if( !this.ShapeContainer.Shapes.Contains( s ))
//								this.ShapeContainer.Shapes.Add( s );
//					}
				#endregion
				
					//Remove shape
					//-------------------------------------------------
					if( this.ShapeContainer.Shapes.Contains( shape))
						this.ShapeContainer.Shapes.Remove(shape);


					RefreshShapeIndexes();
					//				_view.DrawingPanel.InvalidateShapeBounds( Rectangle.Ceiling( bounds ));
					this.ShapeContainer.ResetPath( true );
					_view.DrawingPanel.RecalculateScrollSize();





			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("OnComponentRemoved:"+ exc.StackTrace);
				FileWatcher.WriteLine("OnComponentRemoved:"+ exc.Message);
				throw exc;
			}
		}

		#endregion Event Handlers

		#region ComponentTray Event Handlers

		private void ComponentTray_SizeChanged(object sender, EventArgs e)
		{
			
			try
			{
				if( _view.ComponentTray.Height== this.TrayHeight ) return;


				using(DesignerTransaction tx = this.DesignerHost.CreateTransaction("TrayHeight"))
				{
					PropertyDescriptor prop = TypeDescriptor.GetProperties(this.Component)["TrayHeight"];
					prop.SetValue( this.Component,_view.ComponentTray.Height);
					tx.Commit();
				}
			}
			catch( Exception exc )
			{
				FileWatcher.WriteLine("ComponentTray_SizeChanged:"+ exc.StackTrace);
				FileWatcher.WriteLine("ComponentTray_SizeChanged:"+ exc.Message);
				throw exc;
			}

		}


		private void ComponentTray_VisibleChanged(object sender, EventArgs e)
		{
			try
			{
				if( _view.ComponentTray.Visible== this.TrayVisible) return;

				using(DesignerTransaction tx = this.DesignerHost.CreateTransaction("TrayVisible"))
				{
					PropertyDescriptor prop = TypeDescriptor.GetProperties(this.Component)["TrayVisible"];
					prop.SetValue( this.Component,_view.ComponentTray.Visible);
					tx.Commit();
				}
			}
			catch( Exception exc )
			{
				FileWatcher.WriteLine("ComponentTray_VisibleChanged:"+ exc.StackTrace);
				FileWatcher.WriteLine("ComponentTray_VisibleChanged:"+ exc.Message);
				throw exc;
			}

		}


		#endregion ComponentTray Event Handlers

		#region Designer Verbs
		
		DesignerVerb _verbSnapToGrid = null;
		DesignerVerb _verbShowGrid = null;
		DesignerVerb _verbSaveAs = null;
		DesignerVerbCollection _verbs = null;
		
		public override DesignerVerbCollection Verbs
		{
			get
			{
				try
				{
					if( _verbs == null)
					{
						_verbs = new DesignerVerbCollection();

						_verbSaveAs =    new DesignerVerb("Save As..", new EventHandler(OnSaveAs));
						

						_verbShowGrid =    new DesignerVerb("Show Grid", new EventHandler(OnShowGrid));
						_verbShowGrid.Checked = this.ShowGrid;

						_verbSnapToGrid =    new DesignerVerb("Snap to Grid", new EventHandler(OnSnapToGrid));
						_verbSnapToGrid.Checked = this.SnapToGrid;

					

						_verbs.Add( _verbShowGrid );
						_verbs.Add( _verbSnapToGrid);
						_verbs.Add( _verbSaveAs);

					}

					return _verbs;
				}
				catch( Exception exc)
				{
					FileWatcher.WriteLine("DesignerVerbCollection:"+ exc.StackTrace);
					FileWatcher.WriteLine("DesignerVerbCollection:"+ exc.Message);
					throw exc;
				}
			}
		}




		private void OnSaveAs(object sender, EventArgs e)
		{

			ShapeDesigner.SaveShapeAsPicture( this.ShapeContainer );
		}

		private void OnShowGrid(object sender, EventArgs e)
		{
			try
			{
				using (DesignerTransaction tx = this.DesignerHost.CreateTransaction("ShowGrid"))
				{
					_verbShowGrid.Checked = !this.ShowGrid;
					PropertyDescriptor prop = TypeDescriptor.GetProperties(this.Component)["ShowGrid"];
					prop.SetValue( this.Component,_verbShowGrid.Checked );
					tx.Commit();
				}
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("ShapeContainer::OnShowGrid:"+ exc.StackTrace);
				FileWatcher.WriteLine("ShapeContainer::OnShowGrid:"+ exc.Message);
				throw exc;
			}

		}
		private void OnSnapToGrid(object sender, EventArgs e)
		{
			try
			{
				using (DesignerTransaction tx = this.DesignerHost.CreateTransaction("SnapToGrid"))
				{
					_verbSnapToGrid.Checked = !this.SnapToGrid;
					PropertyDescriptor prop = TypeDescriptor.GetProperties(this.Component)["SnapToGrid"];
					prop.SetValue( this.Component,_verbSnapToGrid.Checked );
					tx.Commit();
				}
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("ShapeContainer::OnSnapToGrid:"+ exc.StackTrace);
				FileWatcher.WriteLine("ShapeContainer::OnSnapToGrid:"+ exc.Message);
				throw exc;
			}


		}

		private void OnMenuSnapToGrid(object sender, EventArgs e)
		{
			OnSnapToGrid( sender, e );
		}

		private void OnMenuShowGrid(object sender, EventArgs e)
		{
			OnShowGrid( sender, e );
		}

		#endregion Designer Verbs

	}


		
}
